﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using BakalarskaPraca.Forms.GenerationSettingsForms;
using BakalarskaPraca.Generation.Data;
using BakalarskaPraca.Generation.Tasks;
using BakalarskaPraca.Generation.Tasks.Abstract;
using BakalarskaPraca.Interfaces;

namespace BakalarskaPraca.Forms
{
    public partial class GenerationInstructionForm : Form, IGenerationProcessSettings
    {
        private class GenerationInstructionItem
        {
            private readonly string _name;
            private readonly IGenerationProcessSettings _settings;
            public GenerationInstructionItem(string name, IGenerationProcessSettings settings)
            {
                this._name = name;
                this._settings = settings;
            }

            public bool ShowSettingsFor(GenerationProcess process)
            {
                return this._settings.ShowSettings(process);
            }

            public GenerationProcess GetGenerationProcess(List<HumidityPolygon> polygons, ModelData modelData)
            {
                return this._settings.GetNewGenerationProcess(polygons, modelData);
            }

            public override string ToString()
            {
                return this._name;
            }
        }

        private readonly ModelData _modelData;
        private List<HumidityPolygon> _polygons;

        public GenerationInstructionForm(ModelData modelData)
        {
            InitializeComponent();
            this._modelData = modelData;
        }

        public List<GenerationProcess> GetGenerationInstructions(List<HumidityPolygon> polygons)
        {
            this.AvalibleTechniqueListBox.Items.Clear();
            this.UsedTechniqueListBox.Items.Clear();
            this._polygons = polygons;

            this.AvalibleTechniqueListBox.Items.Add(new GenerationInstructionItem("HumidityCreation: Casting Shadows", new HumidityShadowCastingSettingsForm()));
            this.AvalibleTechniqueListBox.Items.Add(new GenerationInstructionItem("HumidityCreation: Constant Humidity", new HumidityConstantValueSettingsForm()));
            this.AvalibleTechniqueListBox.Items.Add(new GenerationInstructionItem("PlantDistribution: Plant Simulation", new PlantSimulationDistributionSettingsForm()));
            this.AvalibleTechniqueListBox.Items.Add(new GenerationInstructionItem("PlantDistribution: Grid Filling", new PlantGridDistributionSettingsForm()));
            this.AvalibleTechniqueListBox.Items.Add(new GenerationInstructionItem("PlantDistribution: Dart Throwing", new DartThrowingDistributionSettingsForm()));

            if (this.ShowDialog() == DialogResult.OK)
            {
                return this.UsedTechniqueListBox.Items.Cast<GenerationProcess>().ToList();
            }
            return null;
        }

        private void RemoveTechniqueBtnClick(object sender, EventArgs e)
        {
            if (this.UsedTechniqueListBox.SelectedItem != null)
            {
                UsedTechniqueListBox.Items.Remove(this.UsedTechniqueListBox.SelectedItem);
            }
        }

        private void AddTechniqueBtnClick(object sender, EventArgs e)
        {
            if (this.AvalibleTechniqueListBox.SelectedItem == null) return;
            if (!(this.AvalibleTechniqueListBox.SelectedItem is GenerationInstructionItem)) return;
            
            GenerationInstructionItem item =
                this.AvalibleTechniqueListBox.SelectedItem as GenerationInstructionItem;

            GenerationProcess process = item.GetGenerationProcess(this._polygons, this._modelData);
            
            if (item.ShowSettingsFor(process))
            {
                this.UsedTechniqueListBox.Items.Add(process);
            }
        }

        private void RemoveAllBtnClick(object sender, EventArgs e)
        {
            this.UsedTechniqueListBox.Items.Clear();
        }

        private void MoveUpTechniqueBtnClick(object sender, EventArgs e)
        {
            if (this.UsedTechniqueListBox.SelectedIndex > 0)
            {
                object item = this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex - 1];
                this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex - 1] =
                    this.UsedTechniqueListBox.SelectedItem;
                this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex] = item;
                this.UsedTechniqueListBox.SelectedIndex--;
            }
        }

        private void MoveDownTechniqueBtnClick(object sender, EventArgs e)
        {
            if (this.UsedTechniqueListBox.SelectedIndex < this.UsedTechniqueListBox.Items.Count - 1)
            {
                object item = this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex + 1];
                this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex + 1] =
                    this.UsedTechniqueListBox.SelectedItem;
                this.UsedTechniqueListBox.Items[this.UsedTechniqueListBox.SelectedIndex] = item;
                this.UsedTechniqueListBox.SelectedIndex++;
            }
        }

        private void ProceedBtnClick(object sender, EventArgs e)
        {
            this.DialogResult = DialogResult.OK;
        }

        private void UsedTechniqueListBoxMouseDoubleClick(object sender, MouseEventArgs e)
        {
            this.AvalibleTechniqueListBox.Items.Cast<GenerationInstructionItem>().ToList().ForEach(
                item => item.ShowSettingsFor(this.UsedTechniqueListBox.SelectedItem as GenerationProcess));
        }

        public bool ShowSettings(GenerationProcess generationProcess)
        {
            throw new NotImplementedException();
        }

        public GenerationProcess GetNewGenerationProcess(List<HumidityPolygon> polygons, ModelData modelData)
        {
            throw new NotImplementedException();
        }
    }
}
